#ifndef __INC_QGRDRAW_H__
#define __INC_QGRDRAW_H__

#ifdef _MSC_VER
#pragma once
#endif

//////////////////////////////////////////////////////////////////////////
// font scribe, abstract
class KAPI qgScribe : public kObj
{
	KCH_SUBCLASS(qgScribe, kObj);

	typedef tpl::VecArray<kint> WidArray;

protected:
	WidArray*			_wids;

protected:
	qgScribe();
	~qgScribe();

public:
	virtual bool Analyze(kint size, const char* text) = 0;

	bool PointToX(kint nth, kbool istrail, kint* xloc);
	bool XToPoint(kint xloc, kint* nth, kbool* trail);
};


//////////////////////////////////////////////////////////////////////////
// font

//
#define QGFONT_STYLE_BOLD					K_BIT(0)
#define QGFONT_STYLE_ITALIC					K_BIT(1)

#define QGFONT_SCRIPT_RESET					"\001"
#define QGFONT_SCRIPT_COLOR					"\002"
#define QGFONT_SCRIPT_BOLD					"\003"
#define QGFONT_SCRIPT_ITALIC				"\004"

#define QGFONT_SCRIPT_RESET_L				L"\001"
#define QGFONT_SCRIPT_COLOR_L				L"\002"
#define QGFONT_SCRIPT_BOLD_L				L"\003"
#define QGFONT_SCRIPT_ITALIC_L				L"\004"

// font, abstract
class KAPI qgFont : public qgObj
{
	KCH_SUBCLASS(qgFont, qgObj);

protected:
	tpl::ColorValue		_color;
	kint				_size;
	kint				_style;
	kint				_fmt;

protected:
	qgFont();
	~qgFont() {};

public:
	virtual void CalcPoint(tpl::Point* pt, kint flags, const char* str, kint len = -1) = 0;
	virtual void CalcPointL(tpl::Point* pt, kint flags, const kwchar* uni, kint len = -1) = 0;
	virtual void TextDraw(const tpl::Rect& bound, kint flags, const char* str) = 0;
	virtual void TextDrawL(const tpl::Rect& bound, kint flags, const kwchar* uni) = 0;
	virtual qgScribe* BuildScribe() = 0;

	virtual void SetSize(kint size);

	void Write(kint x, kint y, kint flags, const char* str);
	void WriteFormat(kint x, kint y, kint flags, const char* str, ...);
	void WriteL(kint x, kint y, kint flags, const kwchar* uni);
	void WriteFormatL(kint x, kint y, kint flags, const kwchar* uni, ...);

	void SetColor(const tpl::ColorValue& cc) { _color = cc; }
	void SetStyle(kint style) { _style = style; }

	kint GetSize() { return _size; }
	kint GetStyle() { return _style; }
	const tpl::ColorValue& GetColor() { return _color; }

	tpl::Point CalcSize(kint flags, const char* str) { tpl::Point pt; CalcPoint(&pt, flags, str); return pt; }
	tpl::Point CalcSizeL(kint flags, const kwchar* uni) { tpl::Point pt; CalcPointL(&pt, flags, uni); return pt; }
};


//////////////////////////////////////////////////////////////////////////
// freetype
class KAPI qgFreeType : public qgFont
{
	KCH_SUBCLASS(qgFreeType, qgFont);
	KCH_INTERN(ScribeData);
	KCH_INTERN(CacheData);

protected:
	kint				_maxcache;
	kint				_glyphsize;
	kint				_outsize;

	tpl::Point			_step;

	kSpinLock			_lock;

	CacheData*			_data;

protected:
	explicit qgFreeType(bool systemfont = true);
	~qgFreeType();

public:
	K_OVR void CalcPoint(tpl::Point* pt, kint flags, const char* str, kint len = -1);
	K_OVR void CalcPointL(tpl::Point* pt, kint flags, const kwchar* uni, kint len = -1);
	K_OVR void TextDraw(const tpl::Rect& bound, kint flags, const char* str);
	K_OVR void TextDrawL(const tpl::Rect& bound, kint flags, const kwchar* uni);
	K_OVR qgScribe* BuildScribe();

	K_OVR void SetSize(kint size);
	void SetStep(const tpl::Point& step) { _step = step; }

	kint GetFaceCount();
	kint GetGlyphSize() { return _glyphsize; }
	kint GetOutSize() { return _outsize; }
	kint GetMaxCache() { return _maxcache; }
	const tpl::Point& GetStep() { return _step; }

	kint GetCacheCount();
	void SetCacheCount(kint count);
	void ClearCache();

	bool AddFont(const char* filename, bool preload = false);
	bool AddSystemFont();

	bool CalcPointToX(kint nth, bool istrail, float* xl, const char* text);
	bool CalcPointFromX(float xps, kint* nth, bool* trail, const char* text);

public:
	static qgFreeType* New(bool systemfont = true);
};

#endif	// __INC_QGRDRAW_H__
